/**
 *****************************************************************************
 * @file    hal_irq.h
 * @brief    -
 *
 * Copyright (C) RealMega 2019-2020
 *
 *****************************************************************************
*/
#ifndef __HAL_IRQ_H__
#define __HAL_IRQ_H__


/// Number of IRQ handled by the production driver
#define SYS_IRQ_QTY                              (64)
///sys exception handler
#define SYS_EXC_IRQ                              (5)
// =============================================================================
//  MACROS
// =============================================================================

/// Highest priority 0 - no IRQ are re-enabled during treatment
#define MASK_PRIO_0_IRQS            (0)

#define PRIO_MASK_LPS_IRQ           (MASK_PRIO_0_IRQS)

#define PRIO_0_IRQS                 (SYS_IRQ_SYS_IRQ_LPS)

/// priority 1 - Priority 0 IRQs re-enabled
#define MASK_PRIO_1_IRQS            (MASK_PRIO_0_IRQS|PRIO_0_IRQS)

#ifdef RFSPI_IFC_WORKAROUND
// Allow RFSPI IFC config (TCU1 IRQ) during MCP locking time (TCU0 IRQ),
// so that RFSPI IFC config will never be delayed across the real FINT (TCU wrap event).
// Otherwise RFSPI cmds might NOT be sent to XCV strictly before the first rx win starts at
// next frame, resulting in data lost and wrong data timing. 
#define PRIO_MASK_TCU1_IRQ          (MASK_PRIO_1_IRQS)
#define PRIO_1_IRQS_OPTION_TCU1     (SYS_IRQ_SYS_IRQ_TCU1)
#else // !RFSPI_IFC_WORKAROUND
#define PRIO_1_IRQS_OPTION_TCU1     (0)
#endif // !RFSPI_IFC_WORKAROUND
#define PRIO_MASK_USB_IRQ           (MASK_PRIO_1_IRQS)
#define PRIO_1_IRQS                 (PRIO_1_IRQS_OPTION_TCU1|SYS_IRQ_SYS_IRQ_USBC)

/// priority 2 - Priority 1 and higher IRQs re-enabled
#define MASK_PRIO_2_IRQS            (MASK_PRIO_1_IRQS|PRIO_1_IRQS)

#if defined(PAL_WINDOWS_LOCK_MCP_ON_RX) || defined(DCDC_FREQ_DIV_WORKAROUND)
#define PRIO_MASK_TCU0_IRQ          (MASK_PRIO_2_IRQS)
#define PRIO_2_IRQS_OPTION_TCU0     (SYS_IRQ_SYS_IRQ_TCU0)
#else // !(PAL_WINDOWS_LOCK_MCP_ON_RX || DCDC_FREQ_DIV_WORKAROUND)
#define PRIO_2_IRQS_OPTION_TCU0     (0)
#endif // !(PAL_WINDOWS_LOCK_MCP_ON_RX || DCDC_FREQ_DIV_WORKAROUND)

#define PRIO_2_IRQS                 (PRIO_2_IRQS_OPTION_TCU0)

/// priority 3 - Priority 2 and higher IRQs re-enabled
#define MASK_PRIO_3_IRQS            (MASK_PRIO_2_IRQS|PRIO_2_IRQS)

#define PRIO_MASK_COM0_IRQ          (MASK_PRIO_3_IRQS)

#define PRIO_3_IRQS                 (SYS_IRQ_SYS_IRQ_COM0)

/// priority 4 - Priority 3 and higher IRQs re-enabled
#define MASK_PRIO_4_IRQS            (MASK_PRIO_3_IRQS|PRIO_3_IRQS)

#define PRIO_MASK_FRAME_IRQ         (MASK_PRIO_4_IRQS)

#define PRIO_4_IRQS                 (SYS_IRQ_SYS_IRQ_FRAME)

/// priority 5 - Priority 4 and higher IRQs re-enabled
#define MASK_PRIO_5_IRQS            (MASK_PRIO_4_IRQS|PRIO_4_IRQS)

#define PRIO_MASK_VOC_IRQ           (MASK_PRIO_5_IRQS)

#define PRIO_MASK_BBIFC0_IRQ        (MASK_PRIO_5_IRQS)
#define PRIO_MASK_BBIFC1_IRQ        (MASK_PRIO_5_IRQS)

#define PRIO_5_IRQS                 (SYS_IRQ_SYS_IRQ_BBIFC0| \
                                     SYS_IRQ_SYS_IRQ_BBIFC1| \
                                     SYS_IRQ_SYS_IRQ_VOC)

/// priority 6 - Priority 5 and higher IRQs re-enabled
#define MASK_PRIO_6_IRQS            (MASK_PRIO_5_IRQS|PRIO_5_IRQS)

#define PRIO_MASK_DMA_IRQ           (MASK_PRIO_6_IRQS)
#define PRIO_MASK_GPIO_IRQ          (MASK_PRIO_6_IRQS)
#define PRIO_MASK_TIMERS_IRQ        (MASK_PRIO_6_IRQS)
#define PRIO_MASK_OS_TIMER_IRQ      (MASK_PRIO_6_IRQS)
#define PRIO_MASK_CALENDAR_IRQ      (MASK_PRIO_6_IRQS)
#define PRIO_MASK_SPI_IRQ           (MASK_PRIO_6_IRQS)
#define PRIO_MASK_COM1_IRQ          (MASK_PRIO_6_IRQS)
#define PRIO_MASK_IRC_IRQ           (MASK_PRIO_6_IRQS)
#define PRIO_MASK_PMU               (MASK_PRIO_6_IRQS)

#ifndef PRIO_MASK_TCU0_IRQ
#define PRIO_MASK_TCU0_IRQ          (MASK_PRIO_6_IRQS)
#endif // !PRIO_MASK_TCU0_IRQ

#ifndef PRIO_MASK_TCU1_IRQ
#define PRIO_MASK_TCU1_IRQ          (MASK_PRIO_6_IRQS)
#endif // !PRIO_MASK_TCU1_IRQ

#define PRIO_MASK_UART_IRQ          (MASK_PRIO_6_IRQS)
#define PRIO_MASK_I2C_IRQ           (MASK_PRIO_6_IRQS)
#define PRIO_MASK_BT_IRQ            (MASK_PRIO_6_IRQS)
#define PRIO_MASK_KEYPAD_IRQ        (MASK_PRIO_6_IRQS)

void hal_irq_init(void);
__attribute__((always_inline)) static inline void __enable_irq(void) {
  __asm volatile ("cpsie i" : : : "memory");
}

__attribute__((always_inline)) static inline void __disable_irq(void)
{
  __asm volatile ("cpsid i" : : : "memory");
}


#define HAL_SYS_DISABLE_IRQ()       __disable_irq()
#define HAL_SYS_ENABLE_IRQ()        __enable_irq()

#define HAL_ENABLE_IRQ(irq_num)     NVIC_EnableIRQ(irq_num)
#define HAL_DISABLE_IRQ(irq_num)    NVIC_DisableIRQ(irq_num);

#define HAL_IRQ_HANDLER_SET(irq_num, func_ptr)  NVIC_SetVector(irq_num, func_ptr)
#define HAL_CLEAR_PENDING_IRQ(irq_num)          NVIC_ClearPendingIRQ(irq_num)

#endif


